#pragma once
#ifndef ___MOD_BASIC_STRING_HPP
#define ___MOD_BASIC_STRING_HPP
#include "../config.hpp"
#include "detail.hpp"
namespace
{
}
__MOD_BEGIN
template <class _Elem = char, class _Traits = std::char_traits<_Elem>, class _Alloc = std::allocator<_Elem>>
class basic_string_s :public std::basic_string<_Elem, _Traits, _Alloc>
{
private:
	using _Base = basic_string_s;
	using _Ty = std::basic_string<_Elem, _Traits, _Alloc>;
	using _Alty = std::_Rebind_alloc_t<_Alloc, _Elem>;
	using _Alty_traits = std::allocator_traits<_Alty>;
	using size_type = typename _Alty_traits::size_type;
#if _HAS_CXX17
	template <class _StringViewIsh>
	using _Is_string_view_ish = std::enable_if_t<std::conjunction_v<std::is_convertible<const _StringViewIsh&, std::basic_string_view<_Elem, _Traits>>, std::negation<std::is_convertible<const _StringViewIsh&, const _Elem*>>>, int>;
#endif
public:
	__forceinline operator _Elem* () { return (_Elem*)this->c_str(); }
	__forceinline operator const _Elem* () { return this->c_str(); }
public:
	static constexpr auto npos{ static_cast<size_type>(-1) };
	basic_string_s() noexcept :_Ty() {}
	basic_string_s(const _Base& _Right) :_Ty(_Right) {}
	basic_string_s(const _Ty& _Right) :_Ty(_Right) {}
	basic_string_s(const _Base& _Right, const _Alloc& _Al) : _Ty(_Right, _Al) {}
	basic_string_s(const _Ty& _Right, const _Alloc& _Al) : _Ty(_Right, _Al) {}
	explicit basic_string_s(const _Alloc& _Al) noexcept : _Ty(_Al) {}
	basic_string_s(const _Base& _Right, const size_type _Roff, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Roff, _Al) {}
	basic_string_s(const _Ty& _Right, const size_type _Roff, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Roff, _Al) {}
	basic_string_s(const _Base& _Right, const size_type _Roff, const size_type _Count, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Roff, _Count, _Al) {}
	basic_string_s(const _Ty& _Right, const size_type _Roff, const size_type _Count, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Roff, _Count, _Al) {}
	basic_string_s(const _Elem* const _Ptr, const size_type _Count) : _Ty(_Ptr, _Count) {}
	basic_string_s(const _Elem* const _Ptr, const size_type _Count, const _Alloc& _Al) : _Ty(_Ptr, _Count, _Al) {}
	basic_string_s(const _Elem* const _Ptr) :_Ty(_Ptr) {}
#if _HAS_CXX17
	template <class _Alloc2 = _Alloc, std::enable_if_t<std::_Is_allocator<_Alloc2>::value, int> = 0>
#endif
	basic_string_s(const _Elem* const _Ptr, const _Alloc& _Al) : _Ty(_Ptr, _Al) {}
	basic_string_s(const size_type _Count, const _Elem _Ch) : _Ty(_Count, _Ch) {}
#if _HAS_CXX17
	template <class _Alloc2 = _Alloc, std::enable_if_t<std::_Is_allocator<_Alloc2>::value, int> = 0>
#endif
	basic_string_s(const size_type _Count, const _Elem _Ch, const _Alloc& _Al) : _Ty(_Count, _Ch, _Al) {}
	template <class _Iter, std::enable_if_t<std::_Is_iterator_v<_Iter>, int> = 0>
	basic_string_s(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Ty(_First, _Last, _Al) {}
	basic_string_s(_Base&& _Right) noexcept :_Ty(_Right) {}
	basic_string_s(_Ty&& _Right) noexcept :_Ty(_Right) {}
	basic_string_s(_Base&& _Right, const _Alloc& _Al) noexcept : _Ty(_Right, _Al) {}
	basic_string_s(_Ty&& _Right, const _Alloc& _Al) noexcept : _Ty(_Right, _Al) {}
	basic_string_s(std::_String_constructor_concat_tag, const _Base& _Source_of_al, const _Elem* const _Left_ptr, const size_type _Left_size, const _Elem* const _Right_ptr, const size_type _Right_size) : _Ty(_Source_of_al, _Left_ptr, _Left_size, _Right_ptr, _Right_size) {}
	basic_string_s(std::_String_constructor_concat_tag, const _Ty& _Source_of_al, const _Elem* const _Left_ptr, const size_type _Left_size, const _Elem* const _Right_ptr, const size_type _Right_size) : _Ty(_Source_of_al, _Left_ptr, _Left_size, _Right_ptr, _Right_size) {}
	basic_string_s(std::_String_constructor_concat_tag, _Base& _Left, _Base& _Right) : _Ty(_Left, _Right) {}
	basic_string_s(std::_String_constructor_concat_tag, _Ty& _Left, _Ty& _Right) : _Ty(_Left, _Right) {}
#if _HAS_CXX17
	template <class _StringViewIsh, _Is_string_view_ish<_StringViewIsh> = 0>
	explicit basic_string_s(const _StringViewIsh& _Right, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Al) {}
	template <class _StringViewIsh, _Is_string_view_ish<_StringViewIsh> = 0>
	basic_string_s(const _StringViewIsh& _Right, const size_type _Roff, const size_type _Count, const _Alloc& _Al = _Alloc()) : _Ty(_Right, _Roff, _Count, _Al) {}
#endif
	basic_string_s(std::initializer_list<_Elem> _Ilist, const _Alloc& _Al = _Alloc()) : _Ty(_Ilist, _Al) {}
	~basic_string_s() {}
public:
	_Base& operator=(_Base&& _Right) { _Ty::operator=(_Right); return *this; }
	_Base& operator=(std::initializer_list<_Elem> _Ilist) { _Ty::operator=(_Ilist); return *this; }
	_Base& operator=(const _Base& _Right) { _Ty::operator=(_Right); return *this; }
#if _HAS_CXX17
	template <class _StringViewIsh, _Is_string_view_ish<_StringViewIsh> = 0>
	_Base& operator=(const _StringViewIsh& _Right) { _Ty::operator=(_Right); return *this; }
#endif
	_Base& operator=(const _Elem* const _Ptr) { _Ty::operator=(_Ptr); return *this; }
	_Base& operator=(const _Elem _Ch) { _Ty::operator=(_Ch); return *this; }
public:
	_Base& operator+=(std::initializer_list<_Elem> _Ilist) { _Ty::operator+=(_Ilist); return *this; }
	_Base& operator+=(const _Base& _Right) { _Ty::operator+=(_Right); return *this; }
#if _HAS_CXX17
	template <class _StringViewIsh, _Is_string_view_ish<_StringViewIsh> = 0>
	_Base& operator+=(const _StringViewIsh& _Right) { _Ty::operator+=(_Right); return *this; }
#endif // _HAS_CXX17
	_Base& operator+=(const _Elem* const _Ptr) { _Ty::operator+=(_Ptr); return *this; }
	_Base& operator+=(_Elem _Ch) { _Ty::operator+=(_Ch); return *this; }
public:
	__forceinline void compress()
	{
		size_type index = this->find(_Elem());
		if (index != npos)
		{
			this-
			this->erase(index);
		}
	}
	__forceinline size_type length() const noexcept
	{
		return __mod_string_detail::length(this->data());
	}
	__forceinline void to_upper(std::locale const& loc = std::locale())
	{
		std::use_facet<std::ctype<_Elem>>(loc).toupper(this->begin(), this->end());
	}
	__forceinline void to_lower(std::locale const& loc = std::locale())
	{
		std::use_facet<std::ctype<_Elem>>(loc).tolower(this->begin(), this->end());
	}
	__forceinline void trim(std::locale const& loc = std::locale())
	{
		ltrim(loc);
		rtrim(loc);
	}
	__forceinline void ltrim(std::locale const& loc = std::locale())
	{
		this->erase(this->begin(), std::find_if(this->begin(), this->end(), __mod_string_detail::__mod_not_space<_Elem>(loc)));
	}
	__forceinline void rtrim(std::locale const& loc = std::locale())
	{
		this->erase(std::find_if(this->rbegin(), this->rend(), __mod_string_detail::__mod_not_space<_Elem>(loc)).base(), this->end());
	}
	__forceinline bool equal(const _Elem* const _Right) const noexcept
	{
		size_t len = this->length();
		if (len != __mod_string_detail::length(_Right))
		{
			return false;
		}
		return __mod_string_detail::equal(this->c_str(), _Right, len);
	}
	__forceinline bool contains(_Base const& str)
	{
		return std::search(this->begin(), this->end(), str.begin(), str.end(), __mod_string_detail::__mod_traits_equal<_Elem, _Traits>()) != this->end();
	}
	__forceinline bool icontains(_Base const& str, std::locale const& loc = std::locale())
	{
		return std::search(this->begin(), this->end(), str.begin(), str.end(), __mod_string_detail::__mod_traits_iequal<_Elem, _Traits>(loc)) != this->end();
	}
	__forceinline bool iequal(const _Elem* const _Right) const noexcept
	{
		size_t len = this->length();
		if (len != __mod_string_detail::length(_Right))
		{
			return false;
		}
		return __mod_string_detail::iequal(this->c_str(), _Right, len);
	}
	__forceinline size_t replace(const _Elem* const _Src, const _Elem* const _Dst, size_t _Off = 0, size_t _Count = npos)
	{
		size_t _SrcLength = __mod_string_detail::length(_Src);
		size_t _Pos = _Off;
		size_t _Num = 0;
		while ((_Pos = _Ty::find(_Src, _Pos)) != std::string::npos)
		{
			_Ty::replace(_Pos, _SrcLength, _Dst);
			_Num++;
			if (_Num == _Count)
			{
				break;
			}
		}
		return _Num;
	}
public:
	struct split_results
	{
		const _Base& _This;
		const _Elem* const pattern;
		__forceinline explicit split_results(const _Base& r, const _Elem* const r1) : _This(r), pattern(r1) {}
		__forceinline operator std::vector<_Base>() const { return __mod_string_detail::split<_Elem, _Base>(_This, pattern); }
		__forceinline operator std::vector<_Ty>() const { return __mod_string_detail::split<_Elem, _Ty>(_This, pattern); }
	};
	__forceinline split_results split(const _Elem* const pattern)
	{
		return split_results(*this, pattern);
	}
private:
};
__MOD_END
#endif